"""
@author: 江同学呀
@file: field_value_factor.py
@date: 2025/1/13 20:51
@desc: 
"""
from typing import Union, Literal, Dict

from espc.common.common import Number
from espc.common.query_common import Modifier
from espc.orm.model.base.base import _Base
from espc.orm.model.mapping.field.base_field.base_field import _BaseField


class FieldValueFactor(_Base):
    """
    The field_value_factor function allows you to use a field from a document to influence the score. It’s similar to
    using the script_score function, however, it avoids the overhead of scripting. If used on a multi-valued field,
    only the first value of the field is used in calculations.

    field_value_factor 函数允许您使用文档中的字段来影响分数。这与使用 script_score 函数类似，但是，它避免了脚本编写的开销。如果用于多值
    字段，则计算中仅使用字段的第一个值。
    :param field:
        Field to be extracted from the document.
        要从文档中提取的字段。
    :param factor:
        Optional factor to multiply the field value with, defaults to 1.
        将字段值乘以的可选因子，默认为 1。
    :param modifier:
        Modifier to apply to the field value, can be one of: none, log, log1p, log2p, ln, ln1p, ln2p, square, sqrt, or
        reciprocal. Defaults to none.
        要应用于字段值的修饰符可以是以下值之一：none、log、log1p、log2p、ln、ln1p、ln2p、square、sqrt 或 reciprocal。默认为 none。
    :param missing:
        Value used if the document doesn’t have that field. The modifier and factor are still applied to it as though
        it were read from the document.
        如果文档没有该字段，则使用的值。修饰符和因子仍应用于它，就像它是从文档中读取的一样。
    """

    def __init__(
            self, field: Union[str, _BaseField], factor: Number = None,
            modifier: Union[
                Literal[
                    "none", "log", "log1p", "log2p", "ln", "ln1p", "ln2p", "square", "sqrt", "reciprocal"
                ],
                Modifier
            ] = None,
            missing: Number = None
    ):
        super().__init__()
        self._field: Union[str, _BaseField] = field
        self._factor: float = factor
        self._modifier: Union[
            Literal[
                "none", "log", "log1p", "log2p", "ln", "ln1p", "ln2p", "square", "sqrt", "reciprocal"
            ],
            Modifier,
            None
        ] = modifier
        self._missing: Number = missing
        return

    def _build(self) -> Dict:
        return {
            "field": self._field if isinstance(self._field, str) else self._field._field_name,
            "factor": self._factor,
            "modifier": self._modifier if isinstance(self._modifier, str) else self._modifier.value,
            "missing": self._missing
        }
